#include "light.h"
#include "vector.h"
#include "material.h"
#include "texture.h"
#include <GL/glut.h>
#include <stdio.h>
#include <stdlib.h>

	int on[NUMBER_OF_LIGHTS];
	int i;
	// luce 0 nella stanza 1
	GLfloat position0[] = {55.0, 60.0, 3.0,1.0}; //componente posizionale
	GLfloat diffuse0[] = {0.5,0.4,0.4,1.0}; // componente bianca a diffusione
	GLfloat specular0[] = {0.5,0.5,0.5,1.0}; // componente bianca speculare
	GLfloat ambient0[] = {0.5,0.5,0.4,1.0}; // componente grigia ambientale

	// luce 0 nella stanza 2
	GLfloat position1[] = {112.5, 60.0,3.0,1.0}; //componente posizionale
	GLfloat diffuse1[] = {0.4,0.5,0.4,1.0}; // componente bianca a diffusione
	GLfloat specular1[] = {0.5,0.5,0.5,1.0}; // componente bianca speculare
	GLfloat ambient1[] = {0.3,0.3,0.3,1.0}; // componente grigia ambientale

	// luce 0 nella stanza 3
	GLfloat position2[] = {65, 107.5, 3.0, 1.0}; //componente posizionale
	GLfloat diffuse2[] = {0.7,0.7,0.7,1.0}; // componente bianca a diffusione
	GLfloat specular2[] = {0.5,0.5,0.5,1.0}; // componente bianca speculare
	GLfloat ambient2[] = {0.5,0.5,0.5,1.0}; // componente grigia ambientale

	// luce 0 nella stanza 4
	GLfloat position3[] = {17.5, 60, 3.0,1.0}; //componente posizionale
	GLfloat diffuse3[] = {0.7,0.7,0.7,1.0}; // componente bianca a diffusione
	GLfloat specular3[] = {0.5,0.5,0.7,1.0}; // componente bianca speculare
	GLfloat ambient3[] = {0.5,0.5,0.7,1.0}; // componente grigia ambientale

	// luce 0 nella stanza 5
	GLfloat position4[] = {65, 12.5, 3.0,1.0}; //componente posizionale
	GLfloat diffuse4[] = {0.7,0.7,0.7,1.0}; // componente bianca a diffusione
	GLfloat specular4[] = {0.5,0.5,0.5,1.0}; // componente bianca speculare
	GLfloat ambient4[] = {0.3,0.2,0.2,1.0}; // componente grigia ambientale

	// luce 0 globale
	GLfloat position5[] = {65,55.0, 25.0,1.0}; //componente posizionale
	GLfloat diffuse5[] = {0.3,0.3,0.3,1.0}; // componente bianca a diffusione
	GLfloat specular5[] = {0.3,0.3,0.3,1.0}; // componente bianca speculare
	GLfloat ambient5[] = {0.3,0.3,0.3,1.0}; // componente grigia ambientale
	
	GLfloat spot6[] = {1.0,1.0,-1.0,1.0}; //componente posizionale
	const GLfloat cutoff6[] = {20};
	GLfloat position6[] = {65,60.0,5.0,1.0}; //componente posizionale
	GLfloat diffuse6[] = {0,1,1,1.0}; // componente bianca a diffusione
	GLfloat specular6[] = {0,1,1,1.0}; // componente bianca speculare
	GLfloat ambient6[] = {0,1,1,1.0}; // componente grigia ambientale

	// luce 0 globale
	GLfloat position7[] = {65,55.0, 25.0,1.0}; //componente posizionale
	GLfloat diffuse7[] = {0.8,0.8,0.8,1.0}; // componente bianca a diffusione
	GLfloat specular7[] = {0.5,0.5,0.5,1.0}; // componente bianca speculare
	GLfloat ambient7[] = {0.5,0.5,0.5,1.0}; // componente grigia ambientale
			
void toggleLight(int light){
	on[light] = 1 - on[light]; 
	switch (light){
	case 0:
		if (on[light])
			glEnable(GL_LIGHT0);
		else
			glDisable(GL_LIGHT0);
		break;
	break;
	case 1:
		if (on[light])
			glEnable(GL_LIGHT1);
		else
			glDisable(GL_LIGHT1);
		break;
	case 2:
		if (on[light])
			glEnable(GL_LIGHT2);
		else
			glDisable(GL_LIGHT2);
		break;
	case 3:
		if (on[light])
			glEnable(GL_LIGHT3);
		else
			glDisable(GL_LIGHT3);
		break;
	case 4:
		if (on[light])
			glEnable(GL_LIGHT4);
		else
			glDisable(GL_LIGHT4);
		break;
	case 5:
		if (on[light])
			glEnable(GL_LIGHT6);
		else
			glDisable(GL_LIGHT6);
		break;
	}
}

void addLight(int l){
	switch (l){
		case 0:
			glLightfv(GL_LIGHT0, GL_POSITION, position0);
			glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse0);
			glLightfv(GL_LIGHT0, GL_AMBIENT, ambient0);
			glLightfv(GL_LIGHT0, GL_SPECULAR, specular0);
		break;
		case 1:
			glLightfv(GL_LIGHT1, GL_POSITION, position1);
			glLightfv(GL_LIGHT1, GL_DIFFUSE, diffuse1);
			glLightfv(GL_LIGHT1, GL_AMBIENT, ambient1);
			glLightfv(GL_LIGHT1, GL_SPECULAR, specular1);
		break;
		case 2:
			glLightfv(GL_LIGHT2, GL_POSITION, position2);
			glLightfv(GL_LIGHT2, GL_DIFFUSE, diffuse2);
			glLightfv(GL_LIGHT2, GL_AMBIENT, ambient2);
			glLightfv(GL_LIGHT2, GL_SPECULAR, specular2);
		break;
		case 3:
			glLightfv(GL_LIGHT3, GL_POSITION, position3);
			glLightfv(GL_LIGHT3, GL_DIFFUSE, diffuse3);
			glLightfv(GL_LIGHT3, GL_AMBIENT, ambient3);
			glLightfv(GL_LIGHT3, GL_SPECULAR, specular3);
		break;
		case 4:
			glLightfv(GL_LIGHT4, GL_POSITION, position4);
			glLightfv(GL_LIGHT4, GL_DIFFUSE, diffuse4);
			glLightfv(GL_LIGHT4, GL_AMBIENT, ambient4);
			glLightfv(GL_LIGHT4, GL_SPECULAR, specular4);
			
		break;
		case 5:
			glLightfv(GL_LIGHT5, GL_POSITION, position5);
			glLightfv(GL_LIGHT5, GL_DIFFUSE, diffuse5);
			glLightfv(GL_LIGHT5, GL_AMBIENT, ambient5);
			glLightfv(GL_LIGHT5, GL_SPECULAR, specular5);
		break;
		case 6:
			glLightfv(GL_LIGHT6, GL_POSITION, position6);
			glLightfv(GL_LIGHT6, GL_DIFFUSE, diffuse6);
			glLightfv(GL_LIGHT6, GL_AMBIENT, ambient6);
			glLightfv(GL_LIGHT6, GL_SPECULAR, specular6);
			glLightfv(GL_LIGHT6, GL_SPOT_DIRECTION, spot6);
			glLightfv(GL_LIGHT6, GL_SPOT_CUTOFF, cutoff6);
		break;
		case 7:
			glLightfv(GL_LIGHT7, GL_POSITION, position7);
			glLightfv(GL_LIGHT7, GL_DIFFUSE, diffuse7);
			glLightfv(GL_LIGHT7, GL_AMBIENT, ambient7);
			glLightfv(GL_LIGHT7, GL_SPECULAR, specular7);
		break;

	}
}

void initLight(){
		int l = 0;
		for (l = 0 ; l<NUMBER_OF_LIGHTS; l++) on[l] = 0;
		addLight(0);	
		addLight(1);
		addLight(2);
		addLight(3);
		addLight(4);
		addLight(5);
		addLight(6);
		addLight(7);
		glEnable(GL_LIGHT_MODEL_LOCAL_VIEWER);
		glEnable(GL_LIGHTING);
		glEnable(GL_NORMALIZE);
}

void flashLight(GLfloat eyex, GLfloat eyey, GLfloat eyez,GLfloat  targetx, GLfloat  targety, GLfloat  targetz){
			punto3d* target;
			punto3d* start;

			vettore3d* spotdir;
			
			target = (punto3d*)malloc(sizeof(punto3d*));
			start = (punto3d*)malloc(sizeof(punto3d*));
			spotdir = (vettore3d*)malloc(sizeof(vettore3d*));
			position6[0]=eyex; 
			position6[1]=eyey; 
			position6[2]=eyez;
			start->x=eyex; 
			start->y=eyey; 
			start->z=eyez;
			
			target->x = targetx;
			target->y = targety;
			target->z = targetz;
			vector_diff(spotdir,target,start);
			vector_normalize(spotdir);
			spot6[0] = spotdir->x;
			spot6[1] = spotdir->y;
			spot6[2] = spotdir->z;
			
			glLightfv(GL_LIGHT6, GL_POSITION, position6);
			glLightfv(GL_LIGHT6, GL_DIFFUSE, diffuse6);
			glLightfv(GL_LIGHT6, GL_AMBIENT, ambient6);
			glLightfv(GL_LIGHT6, GL_SPECULAR, specular6);
			glLightfv(GL_LIGHT6, GL_SPOT_DIRECTION, spot6);
			
			glLightf(GL_LIGHT6, GL_SPOT_CUTOFF, 10);
			
}

void lightOnHead(GLfloat eye[3], GLfloat  target[3]) {
			position6[0]= eye[0];
			position6[1]= eye[1];
			position6[2]= 5;
			spot6[0] = eye[0];
			spot6[1] = eye[1];
			spot6[2] = eye[2];

			glLightfv(GL_LIGHT6, GL_POSITION, position6);
			glLightfv(GL_LIGHT6, GL_DIFFUSE, diffuse6);
			glLightfv(GL_LIGHT6, GL_AMBIENT, ambient6);
			glLightfv(GL_LIGHT6, GL_SPECULAR, specular6);
			glLightf(GL_LIGHT6, GL_SPOT_CUTOFF, 20);
}



int fogPosition(GLfloat eye[3], GLfloat target[3]) {

		GLfloat white[4]= {0.3,0.3,0.3,0.2};
		float density, fogstart, fogend;
		float view2d[2];
		float x2d[2] = {1,0};
		view2d[0] = target[0]-eye[0];
		view2d[1] = target[1]-eye[1];
		float normal = sqrt((view2d[0]*view2d[0]) + (view2d[1]*view2d[1])); 
		float distx = 105 - eye[0];
		
		float cosangle = (view2d[0]*x2d[0]+view2d[1]*x2d[1]) / normal;
		if(
			(eye[1]<65.0 && eye[1]>55.0 && (cosangle>0.87)&& eye[0]<105.0)
		) {
			glFogf(GL_FOG_MODE, GL_LINEAR);
			fogstart = fabs(distx);
			fogend = fabs(distx+15);
		}
		else if (eye[0]<120.0 && eye[0]>105.0 && eye[1]<81.0 && eye[1]>45.0){
			//nella stanza
			glFogf(GL_FOG_MODE, GL_EXP);
				density = 0.15;
				glFogf(GL_FOG_DENSITY, density);
		}
		else if (eye[0]<105.0 && eye[0]>85.0 && eye[1]<65.0 && eye[1]>55.0 && cosangle>-0.7){
			glFogf(GL_FOG_MODE, GL_LINEAR);
			fogstart = fabs(distx);
			fogend = fabs(distx+15);
				}
		else if (target[0]<100.0 && target[0]>90.0 && eye[1]<65.0 && target[1]>65.0 && target[1]<76.0){
			glFogf(GL_FOG_MODE, GL_LINEAR);
			fogstart = fabs(distx);
			fogend = fabs(distx+15);
			
			//guardo dalla finestra
		}else{
			glFogf(GL_FOG_MODE, GL_LINEAR);
			fogstart = 200;
			fogend = 300;
		}
	 	glHint(GL_FOG_HINT, GL_NICEST);
		glFogfv(GL_FOG_COLOR, white);

		glFogf(GL_FOG_START, fogstart);
		glFogf(GL_FOG_END, fogend);
}


void enableLightInRoom(room_t* roomMap,GLfloat eyex, GLfloat eyey){
	int currentRoom =	isInRoom(roomMap,eyex, eyey);
	if(currentRoom==1) {
		toggleLight(0);
	}else
	if(currentRoom==2) {
		toggleLight(1);
	}else
	if(currentRoom==3) {
		toggleLight(2);
	}else
	if(currentRoom==4) {
		toggleLight(3);
	}else
	if(currentRoom==5) {
		toggleLight(4);
	}
}

void disableLightLastRoom(room_t* roomMap,GLfloat eye[3], GLfloat newposition[3]){
	int currentRoom =	isInRoom(roomMap,eye[0], eye[1]);
	int nextRoom = isInRoom(roomMap, newposition[0], newposition[1]);
	if(currentRoom!=nextRoom){
		
		switch (currentRoom) {
			case 1:
			break; 
			case 6: case 7: case 8: case 9: 
				on[1] = 0;
				glDisable(GL_LIGHT0);
			break;
			case 2: 
				on[2] = 0;
				glDisable(GL_LIGHT1);
			break;
			case 3: 
				on[3] = 0;
				glDisable(GL_LIGHT2);
			break;
			case 4: 
				on[4] = 0;
				glDisable(GL_LIGHT3);
			break;
			case 5:
				on[5] = 0;
				glDisable(GL_LIGHT4);
			break;
			default:
				glDisable(GL_LIGHT0);
				glDisable(GL_LIGHT1);
				glDisable(GL_LIGHT2);
				glDisable(GL_LIGHT3);
				glDisable(GL_LIGHT4);
		}
		
	}
}

void enableLightNextRoom(room_t* roomMap,GLfloat eye[3], GLfloat newposition[3]) {
	int currentRoom =	isInRoom(roomMap,eye[0], eye[1]);
	int nextRoom = isInRoom(roomMap, newposition[0], newposition[1]);
	if(currentRoom!=nextRoom){
		switch (nextRoom) {
			case 1:
			case 6:
			case 7:
			case 8:
			case 9: 
				on[1] = 1;
				glEnable(GL_LIGHT0);
			break;
			case 2:
				on[2] = 1;
				glEnable(GL_LIGHT1);
			break;
			case 3:
				on[3] = 1;
				glEnable(GL_LIGHT2);
			break;
			case 4:
				on[4] = 1;
				glEnable(GL_LIGHT3);
			break;
			case 5:
				on[5] = 1;
				glEnable(GL_LIGHT4);
			break;
		}
		
	}
}

int shadow(GLfloat eye[3]) {
	float density, fogstart, fogend;
	
	GLfloat black[4]= {0.0,0.0,0.0,1};
	glFogf(GL_FOG_MODE, GL_LINEAR);
	glFogfv(GL_FOG_COLOR, black);
	glFogf(GL_FOG_MODE, GL_LINEAR);
	fogstart = 0;
	fogend = 15;
	glFogf(GL_FOG_START, fogstart);
	glFogf(GL_FOG_END, fogend);
}

int fogEnable(int fog_enable,GLfloat eye[3], GLfloat target[3]) {
		if(fog_enable==0) {
			glDisable(GL_FOG);
			glDisable(GL_LIGHT7);
		}else
		if(fog_enable==1) {
			fogPosition(eye, target);
			glEnable(GL_FOG);
		}
		else if (fog_enable==2){
			shadow(eye);
			glEnable(GL_FOG);
			glEnable(GL_LIGHT7);
		}
		return fog_enable;
}

void disableAllLights () {

	int l = 0;
	for (l = 0 ; l<NUMBER_OF_LIGHTS; l++) on[l] = 0;
	
	glDisable(GL_LIGHT0);
	glDisable(GL_LIGHT1);
	glDisable(GL_LIGHT2);
	glDisable(GL_LIGHT3);
	glDisable(GL_LIGHT4);
	glDisable(GL_LIGHT5);
	glDisable(GL_LIGHT6);
}